/*******************************************************************************
* Copyright (c) 2008 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kaloyan Raev, kaloyan.raev@sap.com - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.j2ee.internal.common.operations;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.ABSTRACT_METHODS;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.CLASS_NAME;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.CONSTRUCTOR;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.INTERFACES;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.JAVA_PACKAGE;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.MODIFIER_ABSTRACT;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.MODIFIER_FINAL;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.MODIFIER_PUBLIC;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.PROJECT;
import static org.eclipse.jst.j2ee.internal.common.operations.INewJavaClassDataModelProperties.SUPERCLASS;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
public class CreateJavaEEArtifactTemplateModel {
public static final String ATT_NAME = "name"; //$NON-NLS-1$
public static final String ATT_DESCRIPTION = "description"; //$NON-NLS-1$
/**
* Constant representing no compatibility flag.
*/
public static final int FLAG_NONE = 0x00000000;
/**
* Constant representing the <i>Qualified Superclass Name</i> compatibility
* flag.
*
* <p>
* When this flag is set then the {@link #getSuperclassName()} method always
* returns the qualified name of the superclass.
* </p>
*
* @see #getSuperclassName()
*/
public static final int FLAG_QUALIFIED_SUPERCLASS_NAME = 0x00000001;
/**
* Constant representing a combination of all possible compatibility flags.
*/
public static final int FLAG_ALL = 0xffffffff;
/**
* Compatibility flags.
*
* @see #addFlags(int)
* @see #removeFlags(int)
* @see #FLAG_NONE
* @see #FLAG_QUALIFIED_SUPERCLASS_NAME
* @see #FLAG_ALL
*/
protected int flags;
protected IDataModel dataModel;
public CreateJavaEEArtifactTemplateModel(IDataModel dataModel) {
this.dataModel = dataModel;
this.flags = FLAG_QUALIFIED_SUPERCLASS_NAME;
}
/**
* Adds compatibility flags represented by the given bitmask.
*
* @param bitmask -
* represents the flags to add.
*
* @see #addFlags(int)
* @see #removeFlags(int)
* @see #FLAG_NONE
* @see #FLAG_QUALIFIED_SUPERCLASS_NAME
* @see #FLAG_ALL
*/
public void addFlags(int bitmask) {
flags = flags | bitmask;
}
/**
* Removes compatibility flags represented by the given bitmask.
*
* @param bitmask -
* represents the flags to remove.
*
* @see #addFlags(int)
* @see #removeFlags(int)
* @see #FLAG_NONE
* @see #FLAG_QUALIFIED_SUPERCLASS_NAME
* @see #FLAG_ALL
*/
public void removeFlags(int bitmask) {
flags = flags & ~bitmask;
}
/**
* Check if compatibility flags, represented by the given bitmask, are set.
*
* @param bitmask -
* represents the flags to check.
*
* @return <code>true</code> - if all of the given flags are set,
* <code>false</code> - if any of the given flags is not set.
*
* @see #addFlags(int)
* @see #removeFlags(int)
* @see #FLAG_NONE
* @see #FLAG_QUALIFIED_SUPERCLASS_NAME
* @see #FLAG_ALL
*/
public boolean areFlagsSet(int bitmask) {
return (flags & bitmask) != 0;
}
public Collection<String> getImports() {
Collection<String> collection = new ImportsCollection(this);
String className = getClassName();
String superclassName = getQualifiedSuperclassName();
if (superclassName != null && superclassName.length() > 0 &&
!areFlagsSet(FLAG_QUALIFIED_SUPERCLASS_NAME) &&
!equalSimpleNames(className, superclassName)) {
collection.add(superclassName);
}
List<String> interfaces = getQualifiedInterfaces();
if (interfaces != null) {
for (String iface : interfaces) {
if (!equalSimpleNames(getClassName(), iface)) {
collection.add(iface);
}
}
}
List<Constructor> constructors = getConstructors();
for (Constructor constructor : constructors) {
List<String> types = constructor.getNonPrimitiveParameterTypes();
for (String type : types) {
collection.add(type);
}
}
Collection<Method> methods = getUnimplementedMethods();
for (Method method : methods) {
collection.addAll(method.getParameterImports());
collection.addAll(method.getReturnTypeImports());
}
return collection;
}
public String getClassName() {
return getProperty(CLASS_NAME).trim();
}
public String getJavaPackageName() {
return getProperty(JAVA_PACKAGE).trim();
}
public String getQualifiedJavaClassName() {
return getJavaPackageName() + "." + getClassName(); //$NON-NLS-1$
}
public String getSuperclassName() {
String qualified = getQualifiedSuperclassName();
if (areFlagsSet(FLAG_QUALIFIED_SUPERCLASS_NAME) || equalSimpleNames(getClassName(), qualified)) {
return qualified;
}
return Signature.getSimpleName(qualified);
}
public String getQualifiedSuperclassName() {
return getProperty(SUPERCLASS).trim();
}
public List<String> getInterfaces() {
List<String> qualifiedInterfaces = getQualifiedInterfaces();
List<String> interfaces = new ArrayList<String>(qualifiedInterfaces.size());
for (String qualified : qualifiedInterfaces) {
if (equalSimpleNames(getClassName(), qualified)) {
interfaces.add(qualified);
} else {
interfaces.add(Signature.getSimpleName(qualified));
}
}
return interfaces;
}
public List<String> getQualifiedInterfaces() {
List<String> interfaces = (List<String>) dataModel.getProperty(INTERFACES);
return (interfaces == null) ? new ArrayList<String>() : interfaces;
}
public boolean isPublic() {
return dataModel.getBooleanProperty(MODIFIER_PUBLIC);
}
public boolean isFinal() {
return dataModel.getBooleanProperty(MODIFIER_FINAL);
}
public boolean isAbstract() {
return dataModel.getBooleanProperty(MODIFIER_ABSTRACT);
}
public boolean shouldGenSuperclassConstructors() {
return dataModel.getBooleanProperty(CONSTRUCTOR);
}
public boolean shouldImplementAbstractMethods(){
return dataModel.getBooleanProperty(ABSTRACT_METHODS);
}
public boolean hasEmptySuperclassConstructor() {
List<Constructor> constructors = getConstructors();
for (Constructor constructor : constructors) {
if (constructor.isParameterless())
return true;
}
return false;
}
public List<Constructor> getConstructors() {
List<Constructor> constrs = new ArrayList<Constructor>();
String superclass = dataModel.getStringProperty(SUPERCLASS);
if (superclass != null && superclass.length() > 0) {
IProject p = (IProject) dataModel.getProperty(PROJECT);
IJavaProject javaProject = JavaCore.create(p);
if (javaProject != null) {
try {
IType type = javaProject.findType(superclass);
if (type != null) {
if (type.isBinary()) {
IMethod[] methods = type.getMethods();
for (IMethod method : methods) {
if (method.isConstructor())
constrs.add(new BinaryConstructor(method));
}
} else {
ICompilationUnit compilationUnit = type.getCompilationUnit();
TypeDeclaration declarationFromType = getTypeDeclarationFromType(superclass, compilationUnit);
if (declarationFromType != null) {
MethodDeclaration[] methods = declarationFromType.getMethods();
for (MethodDeclaration method : methods) {
if (method.isConstructor())
constrs.add(new SourceConstructor(method));
}
}
}
}
} catch (JavaModelException e) {
J2EEPlugin.logError(e);
}
}
}
return constrs;
}
public Collection<Method> getUnimplementedMethods() {
Collection<Method> unimplementedMethods = new HashSet<Method>();
if (shouldImplementAbstractMethods()) {
IJavaProject javaProject = getJavaProject();
List<String> interfaces = getQualifiedInterfaces();
for (String iface : interfaces) {
try {
IType type = javaProject.findType(iface);
if (type != null)
getUnimplementedMethod0(type, unimplementedMethods);
} catch (JavaModelException e) {
J2EEPlugin.logError(e);
}
}
}
return unimplementedMethods;
}
private void getUnimplementedMethod0(IType type, Collection<Method> unimplementedMethods) throws JavaModelException {
IJavaProject javaProject = getJavaProject();
if (type.isBinary()) {
IMethod[] methods = type.getMethods();
for (IMethod method : methods) {
unimplementedMethods.add(new BinaryMethod(method));
}
// process super interfaces
String[] superInterfaces = type.getSuperInterfaceNames();
for (String superInterface : superInterfaces) {
IType superInterfaceType = javaProject.findType(superInterface);
if (superInterfaceType != null)
getUnimplementedMethod0(superInterfaceType, unimplementedMethods);
}
} else {
ICompilationUnit compilationUnit = type.getCompilationUnit();
TypeDeclaration declarationFromType = getTypeDeclarationFromType(type.getFullyQualifiedName(), compilationUnit);
if (declarationFromType != null) {
MethodDeclaration[] methods = declarationFromType.getMethods();
for (MethodDeclaration method : methods) {
unimplementedMethods.add(new SourceMethod(method));
}
// process super interfaces
List<Type> superInterfaces = declarationFromType.superInterfaceTypes();
for (Type superInterface : superInterfaces) {
ITypeBinding binding = superInterface.resolveBinding();
IType superInterfaceType = javaProject.findType(binding.getQualifiedName());
if (superInterfaceType != null)
getUnimplementedMethod0(superInterfaceType, unimplementedMethods);
}
}
}
}
protected String getProperty(String propertyName) {
return dataModel.getStringProperty(propertyName);
}
protected boolean equalSimpleNames(String name1, String name2) {
String simpleName1 = Signature.getSimpleName(name1);
String simpleName2 = Signature.getSimpleName(name2);
return simpleName1.equals(simpleName2);
}
protected IJavaProject getJavaProject() {
IProject p = (IProject) dataModel.getProperty(PROJECT);
return JavaCore.create(p);
}
private TypeDeclaration getTypeDeclarationFromType(String typeName, ICompilationUnit unit) {
CompilationUnit cu = (CompilationUnit) parse(unit);
Iterator iterator = cu.types().iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
if (obj instanceof TypeDeclaration) {
TypeDeclaration declaration = (TypeDeclaration) obj;
ITypeBinding tb = declaration.resolveBinding();
if (tb != null) {
String declarationName = tb.getQualifiedName();
if (typeName.equals(declarationName)) {
return declaration;
}
}
}
}
return null;
}
private ASTNode parse(ICompilationUnit unit) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(unit);
parser.setResolveBindings(true);
parser.setStatementsRecovery(true);
return parser.createAST(null);
}
}